package com.bys.security;

import com.bys.exception.BysOaSystemException;
import com.bys.response.Result;
import com.bys.response.ReultCode;
import com.bys.system.model.SysUserModel;
import com.bys.system.vo.LoginUserVo;
import com.bys.util.JwtUtil;
import com.bys.util.RespUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * 登录过滤器
 */
@Slf4j
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
    private final StringRedisTemplate redisTemplate;
    public TokenLoginFilter(AuthenticationManager manager,StringRedisTemplate redisTemplate) {
        this.setAuthenticationManager(manager);
        //是否只能为 post 请求
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/system/sysUser/login","POST"));
        this.redisTemplate = redisTemplate;
    }

    /**
     * 登录 认证
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            LoginUserVo loginUserVo = new ObjectMapper().readValue(request.getInputStream(),LoginUserVo.class);
            UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(loginUserVo.getUsername(),loginUserVo.getPassword());
            // 开始认证
            return this.getAuthenticationManager().authenticate(authToken);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *  认证成功
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
        CrmUser crmUser = (CrmUser) auth.getPrincipal();
        SysUserModel userModel = crmUser.getSysUserModel();
        log.info("认证后的登录对象 {}", userModel);
        String token = JwtUtil.createToken(userModel.getId(), userModel.getUsername());
        redisTemplate.opsForValue().set(token,new ObjectMapper().writeValueAsString(crmUser.getAuthorities()));
        Map<String,String> map = new HashMap<>();
        map.put("token",token);
        RespUtils.sendData(response,Result.success(map));
    }

    /**
     * 认证失败
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        log.info("这里报错 =====");
        RespUtils.sendData(response,Result.fail(ReultCode.LOGIN_ERROR));
    }
}
